package com.bocloud.cmp.driver.providers.ali;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.ecs.model.v20140526.DescribeInstanceTypesRequest;
import com.aliyuncs.ecs.model.v20140526.DescribeInstanceTypesResponse;
import com.aliyuncs.ecs.model.v20140526.DescribeInstanceTypesResponse.InstanceType;
import com.aliyuncs.ecs.model.v20140526.DescribeRegionsRequest;
import com.aliyuncs.ecs.model.v20140526.DescribeRegionsResponse;
import com.aliyuncs.ecs.model.v20140526.DescribeRegionsResponse.Region;
import com.aliyuncs.ecs.model.v20140526.DescribeZonesRequest;
import com.aliyuncs.ecs.model.v20140526.DescribeZonesResponse;
import com.aliyuncs.ecs.model.v20140526.DescribeZonesResponse.Zone;
import com.aliyuncs.exceptions.ClientException;
import com.bocloud.cmp.driver.providers.LocationDriver;
import com.bocloud.cmp.model.FlavorModel;
import com.bocloud.cmp.model.RegionModel;
import com.bocloud.cmp.model.ZoneModel;
import com.bocloud.common.model.BsmResult;
import com.google.common.collect.Lists;

public class AliLocationDriver extends AliDriver implements LocationDriver {
	private static Logger logger = LoggerFactory.getLogger(AliLocationDriver.class);

	/**
	 * 
	 */
	public AliLocationDriver() {
		super();
	}

	/**
	 * @param accessKey
	 * @param secretKey
	 * @param regionId
	 */
	public AliLocationDriver(String accessKey, String secretKey, String regionId) {
		super(accessKey, secretKey, regionId);
	}

	@Override
	public BsmResult listRegions() {
		BsmResult result = null;
		DescribeRegionsRequest request = new DescribeRegionsRequest();
		try {
			DescribeRegionsResponse response = this.getClient().getAcsResponse(request);
			List<Region> regions = response.getRegions();
			result = new BsmResult(true, regions, "success");
		} catch (ClientException e) {
			logger.error("listRegions error:", e);
			result = new BsmResult(false, e.getErrMsg());
		}
		return result;
	}

	@Override
	public BsmResult listZones(String region) {
		BsmResult result = null;
		DescribeZonesRequest request = new DescribeZonesRequest();
		request.setRegionId(region);
		try {
			DescribeZonesResponse response = this.getClient().getAcsResponse(request);
			List<Zone> zones = response.getZones();
			result = new BsmResult(true, zones, "success");
		} catch (ClientException e) {
			logger.error("listRegions error:", e);
			result = new BsmResult(false, e.getErrMsg());
		}
		return result;
	}

	@Override
	public BsmResult sync() {
		BsmResult result = null;
		Map<String, Object> data = new HashMap<>();
		List<RegionModel> regionModels = Lists.newArrayList();
		List<FlavorModel> flavors = Lists.newArrayList();
		DescribeRegionsRequest request = new DescribeRegionsRequest();
		try {
			DescribeRegionsResponse response = this.getClient().getAcsResponse(request);
			List<Region> regions = response.getRegions();
			if (null == regions || regions.isEmpty()) {
				data.put("region", regionModels);
				data.put("flavor", flavors);
				return new BsmResult(true, data, "没有可用区域！");
			}

			for (Region region : regions) {
				RegionModel model = this.convertRegion(region);
				DescribeZonesRequest describeZonesRequest = new DescribeZonesRequest();
				describeZonesRequest.setRegionId(region.getRegionId());
				DescribeZonesResponse describeZonesResponse = this.getClient().getAcsResponse(describeZonesRequest);
				List<Zone> zones = describeZonesResponse.getZones();
				model.setZones(this.convertZones(zones, region.getRegionId()));
				regionModels.add(model);
			}
			DescribeInstanceTypesRequest describeInstanceTypesRequest = new DescribeInstanceTypesRequest();
			request.setRegionId(this.getRegionId());
			DescribeInstanceTypesResponse describeInstanceTypesResponse = this.getClient()
					.getAcsResponse(describeInstanceTypesRequest);
			List<InstanceType> instancesTypes = describeInstanceTypesResponse.getInstanceTypes();
			for (InstanceType instanceType : instancesTypes) {
				FlavorModel flavorModel = new FlavorModel();
				flavorModel.setCpu(instanceType.getCpuCoreCount());
				flavorModel.setMemory(
						new BigDecimal(instanceType.getMemorySize()).multiply(new BigDecimal(1024)).intValue());
				flavorModel.setFamily(instanceType.getInstanceTypeFamily());
				flavorModel.setName(instanceType.getInstanceTypeId());
				flavors.add(flavorModel);
			}
			data.put("region", regionModels);
			data.put("flavor", flavors);
			result = new BsmResult(true, data, "success");
		} catch (ClientException e) {
			logger.error("listRegions error:", e);
			result = new BsmResult(false, e.getErrMsg());
		}
		return result;
	}

	private RegionModel convertRegion(Region region) {
		RegionModel model = new RegionModel();
		model.setCode(region.getRegionId());
		model.setName(region.getLocalName());
		model.setRegionId(region.getRegionId());
		return model;
	}

	private List<ZoneModel> convertZones(List<Zone> zones, String region) {
		List<ZoneModel> models = Lists.newArrayList();
		if (null == zones || zones.isEmpty()) {
			return models;
		}
		for (Zone zone : zones) {
			ZoneModel model = new ZoneModel();
			model.setName(zone.getLocalName());
			model.setRegionId(region);
			model.setZoneId(zone.getZoneId());
			model.setResources(JSONObject.toJSONString(zone.getAvailableResources()));
			model.setDiskCategory(convertDiskCategory(zone.getAvailableDiskCategories()));
			models.add(model);
		}
		return models;
	}

	private String convertDiskCategory(List<String> categorys) {
		StringBuffer stringBuffer = new StringBuffer();
		if (null == categorys || categorys.isEmpty()) {
			return stringBuffer.toString();
		}
		for (String category : categorys) {
			if (category.equalsIgnoreCase("cloud")) {
				stringBuffer.append(category.toUpperCase()).append(",");
			} else {
				stringBuffer.append(category.split("_")[1].toUpperCase()).append(",");
			}
		}
		stringBuffer.deleteCharAt(stringBuffer.length() - 1);
		return stringBuffer.toString();
	}

}
